--This 2d3d browser don't use the chrome module and mouse and keyboard inputs are not working in this one.
include("shared.lua");
AccessorFunc(ENT,"b_KeepValid","KeepValid",FORCE_BOOL); -- Keep the panel ALWAYS valid? Means, if it's getting destroyed (e.g. arbage Collected), it will be created new.
AccessorFunc(ENT,"b_MouseEnabled","EnableMouse",FORCE_BOOL); -- Enable the mouse to be drawn

local RT_SIZE = {1024,1024}; -- Size of the render target, defined in /settings/render_targets/PanelRT.txt.

--################### Init @aVoN
function ENT:Initialize()
	self.__Resolution = 1;
	-- Used in GetMaxSize
	self.MaxW = math.Clamp(ScrW(),0,RT_SIZE[1]);
	self.MaxH = math.Clamp(ScrH(),0,RT_SIZE[2]);
	self:SetKeepValid(true);
end

--################### Creates the rendertarget and a material we draw it on later @aVoN
-- It only creates it ONCE to save performance and memory
local RT;
local RT_INVALID;
local MATERIAL;

-- Called in DrawTranslucent. Reason: If we create it when the map loads, it's invalid. So we only do if this SENT is loaded and only ONCE.
function ENT:InitializeRenderTarget()
	if(RT or RT_INVALID) then return end;
	-- Fetch the render-target
	RT = GetRenderTarget("PanelRT",RT_SIZE[1],RT_SIZE[2]);
	if(not RT) then RT_INVALID = true return end; -- Disable this function getting called again and initializes a warning message
	-- Create a Material we allocate the texture to
	MATERIAL = CreateMaterial("PanelRT","UnlitGeneric",
		{
			["$vertexcolor"] = 1,
		}
	);
	MATERIAL:SetMaterialTexture("$basetexture",RT); -- Tell the material, it's going to use the rendertarget as texture
end

--################### Get/Set a Panel we want to draw in 3D-Space @aVoN
-- You better just call this if you want to change a panel. If you initialize the sent, better use ENT:CreatePanel() which is a hook and called by this SENT as soon as "everything is ready".
function ENT:SetPanel(panel)
	if(not IsValid(panel)) then return false end;
	self.__Panel = panel;
	self.__Panel:SetPaintedManually(true); -- Makes it NOT draw on the HUD. We do manually draw it!
	return true;
end
function ENT:GetPanel() return self.__Panel end;

--################### Set/GetSize of the panel
function ENT:SetSize(w,h) self.__W,self.__H = w,h end;
function ENT:GetSize() return (self.__W or 0),(self.__H or 0) end;
function ENT:GetMaxSize() return self.MaxW,self.MaxH end;

--################### Sets the resolution: Scales the texture @aVoN
-- Input: Float. 1 = 100%
function ENT:SetResolution(r) self.__Resolution = r end;
function ENT:GetResolution() return self.__Resolution end;

--################### Draw @aVoN
local info = surface.GetTextureID("gui/info");
local endpos = Vector(0,0,0);
local i = 0;

function ENT:Draw()
	--############ Panel Load Hook
	local valid = IsValid(self.__Panel);
	if(not self.__Loaded or (not valid and self.b_KeepValid and self.CreatePanel)) then
		if(self.CreatePanel) then
			local panel = self:CreatePanel();
			if(not IsValid(panel)) then return end;
			valid = true;
			self:SetPanel(panel);
			if(self.OnPanelCreated) then self:OnPanelCreated(panel) end; -- Anything to do after panel is created?
		end
		self.__Loaded = true;
		return;
	end
	
	--############ Validity checks
	if(self.SinglePlayer) then self.Entity:DrawModel() end; -- Just here for debugging and setting the SENT in singleplayer
	if(not (self.__W and self.__H and self.__W > 0 and self.__H > 0)) then return end; -- No size?
	if(not valid) then self.__Panel = nil return end; -- Became invalid or isn't valid? STOP
	
	self:InitializeRenderTarget(); -- Creates the render-target we want to draw on
	
	--############ Make this prop draw as long as it's in "vision"
	endpos.x = self.__W;
	endpos.y = -1*self.__H;
	self.Entity:SetRenderBounds(vector_origin,endpos);
	
	local pos = self:GetPos();
	local ang = self:GetAngles();
	
	--############ RT is not valid -> User joined first time without having the RT. tell him to restart GMod
	-- I know, I could just draw the VGUI right here, but it results to errors. Especially on the HTML-Vgui which I'm mainly using (pink-black checkboards, pixelish view etc).
	if(RT_INVALID) then
		cam.Start3D2D(pos,ang,0.4);
			local w,h = self.__W*2.5,self.__H*2.5;
			surface.SetDrawColor(0,0,0,255);
			surface.DrawRect(0,0,w,h);
			surface.SetTexture(info);
			surface.SetDrawColor(255,255,255,255);
			surface.DrawTexturedRect(w/2 - 16,h/2 - 48,32,32);
			draw.SimpleText("Restart Garry's Mod","default",w/2,h/2 - 10,color_white,TEXT_ALIGN_CENTER);
			draw.SimpleText("in order to see","default",w/2,h/2,color_white,TEXT_ALIGN_CENTER);
			draw.SimpleText("these screens","default",w/2,h/2 + 10,color_white,TEXT_ALIGN_CENTER);
		cam.End3D2D();
		return;
	end
	
	--############ Draw the VGUI manually on a new ViewPort and allocate the drawn data to the rendertarget
	-- Method from the "WireGPU". It fixes the issue of the pink-black texture if the VGUI isn't sized to exactly a multiple of 2^n in width and height. It also makes it look smooth
	local OldW,OldH = ScrW(),ScrH();
	local OldRT = render.GetRenderTarget();
	local w,h = self.__W*self.__Resolution,self.__H*self.__Resolution;
	render.SetRenderTarget(RT);
	render.ClearRenderTarget(RT,color_black); -- Avoids issues where sometimes not fully initialized "adverts" show the content of "another advert" -> Clear the RT with black
	render.SetViewPort(0,0,w,h); -- Cuts off everything which is draw OVER the edges. Fixes the issue with drawing the black-purple shit
	
	self.__Panel:SetPaintedManually(false); -- This idea came from Xera and OliverHamel: We deactivate SetPaintedManually for a moment, draw now on the screen and reactivate it again --http://www.facepunch.com/showthread.php?t=635875
	cam.Start2D();
		if(self.PrePanelDraw) then self:PrePanelDraw(self.__Panel,w,h) end; -- Allows drawing before the panel is drawn
		surface.SetDrawColor(255,255,255,255);
		self.__Panel:PaintManual();
	cam.End2D();
	self.__Panel:SetPaintedManually(true);

	render.SetViewPort(0,0,OldW,OldH);
	render.SetRenderTarget(OldRT);
	
	--############ Now actually draw the newly created render-target threedimensional in the world
	cam.Start3D2D(pos,ang,1/self.__Resolution);
		surface.SetMaterial(MATERIAL);
		surface.SetDrawColor(255,255,255,255);
		surface.DrawTexturedRectScaled(0,0,w,h,math.Clamp(w/RT_SIZE[1],0,1),math.Clamp(h/RT_SIZE[2],0,1));
		if(self.PostPanelDraw) then self:PostPanelDraw(self.__Panel,w,h) end; -- Allows drawing after the panel is drawn
		-- The mouse is ALWAYS drawn ontop. Even ontop PostPanelDraw
		if(self.b_MouseEnabled or true) then
			local p = LocalPlayer();
			local ppos = self.Entity:WorldToLocal(p:GetShootPos());
			if(ppos.z > 0) then -- Player is infront of it
				local norm = self.Entity:WorldToLocal(pos + p:GetAimVector());
				if(norm.z < 0) then -- And he aims in it's direction
					local mul = -1*ppos.z/norm.z; -- How much times we need to multiplay norm.z in order to reach the point z=0 starting from ppos.z (z=0 means: On the surface)
					local HitX = ppos.x + norm.x*mul
					local HitY = -1*(ppos.y + norm.y*mul);
					if(HitX > 0 and HitX < self.__W and HitY > 0 and HitY < self.__H) then -- Within the panel: Draw the mouse
						
					end
				end
			end
		end
	cam.End3D2D();
	-- In MultiPlayer, draw this also with an offset to fix an nVidea bug
	if(self.SinglePlayer) then
		cam.Start3D2D(pos + self.Entity:GetUp(),ang,1/self.__Resolution);
			surface.SetMaterial(MATERIAL);
			surface.SetDrawColor(255,255,255,255);
			surface.DrawTexturedRectScaled(0,0,w,h,math.Clamp(w/RT_SIZE[1],0,1),math.Clamp(h/RT_SIZE[2],0,1));
			if(self.PostPanelDraw) then self:PostPanelDraw(self.__Panel,w,h) end; -- Allows drawing after the panel is drawn
		cam.End3D2D();
	end
end

--################### Draws a "texture-quad", but can scales the texture on it. @aVoN
-- Let's say, you have a 512x512 texture where only 512x256 is drawn on - The rest 256 pixels are black. Now you just want to draw the non-black parts.
-- This is getting achieved by capping off the rest using surface.DrawPoly.
-- Example: 512x256 image in a 512x512 texture: Set W = 512, H = 256 and x_scale = 1, y_scale = 2
-- The last y_scale = 2 makes the texture stretch by 2 so the "bottom half" which does not contain anything (512x256 is just has an image) is not drawn
local POLYGON = {{{},{},{}},{{},{},{}}}; -- Two polygons

local function SetVertexData(VERTEX,x,y,u,v)
	VERTEX.x = x;
	VERTEX.y = y;
	VERTEX.u = u;
	VERTEX.v = v;
end

function surface.DrawTexturedRectScaled(x,y,w,h,x_scale,y_scale)
	local x_scale,y_scale = x_scale or 1,y_scale or 1;
	--############ First Polygon
	--First Vertex - Top left
	SetVertexData(POLYGON[1][1],x,y,0,0);
	--Second Vertex - Top right
	SetVertexData(POLYGON[1][2],x+w,y,x_scale,0);
	--Third Vertex - Bottom left
	SetVertexData(POLYGON[1][3],x,y+h,0,y_scale);
	--############ Second Polygon
	--First Vertex - Top Right
	SetVertexData(POLYGON[2][1],x+w,y,x_scale,0);
	--Second Vertex - Bottom right
	SetVertexData(POLYGON[2][2],x+w,y+h,x_scale,y_scale);
	--Third Vertex - Bottom left
	SetVertexData(POLYGON[2][3],x,y+h,0,y_scale);
	surface.DrawPoly(POLYGON[1]);
	surface.DrawPoly(POLYGON[2]);
end

--################### Remove the panel if the SENT is getting deleted @aVoN
function ENT:OnRemove()
	if(IsValid(self.__Panel)) then
		if(self.OnPanelRemove) then
			self:OnPanelRemove(self.__Panel); -- Calls an OnRemove hook for the panel
		end
		self.__Panel:Remove(); -- Remove it
	end
end